package iso8583

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
)

//Header 报文头
type Header struct {
	Heads   []Head
	HeadLen int
	Len     int
}

//Head 头单个元素
type Head struct {
	IsExit      bool   //是否存在
	Type        int    //类型 固定 可变LL 长可变LLL
	Len         int    //字节长度
	Data        []byte //字节数据
	DataStr     string
	funcDataStr func([]byte) string //第几域
}

//ParseStr 解析字符串
var ParseStr = func(b []byte) string {

	return string(b)
}

//NewHeader 创建报文头
func NewHeader() *Header {
	h := &Header{
		Heads:   make([]Head, 11, 11),
		HeadLen: 46,
	}

	h.Heads[0] = Head{
		IsExit: false,
		funcDataStr: func(b []byte) string {
			return "放弃域，不使用"
		},
	}
	h.Heads[1] = Head{
		IsExit: true,
		Len:    1,
		Type:   FIX,
		funcDataStr: func(b []byte) string {
			return fmt.Sprintf("%d", b[0])
		},
	}
	h.Heads[2] = Head{
		IsExit: true,
		Len:    1,
		Type:   FIX,
		funcDataStr: func(b []byte) string {
			b3 := b[0]
			return fmt.Sprintf("%d", b3)
		},
	}
	h.Heads[3] = Head{
		IsExit:      true,
		Len:         4,
		Type:        FIX,
		funcDataStr: ParseStr,
	}
	h.Heads[4] = Head{
		IsExit:      true,
		Len:         11,
		Type:        FIX,
		funcDataStr: ParseStr,
	}
	h.Heads[5] = Head{
		IsExit:      true,
		Len:         11,
		Type:        FIX,
		funcDataStr: ParseStr,
	}
	h.Heads[6] = Head{
		IsExit: true,
		Len:    3,
		Type:   FIX,
		funcDataStr: func(b []byte) string {
			var s string
			for i := range b {
				s += fmt.Sprintf("%d", b[i])
			}
			return s
		},
	}
	h.Heads[7] = Head{
		IsExit: true,
		Len:    1,
		Type:   FIX,
		funcDataStr: func(b []byte) string {
			return fmt.Sprintf("%d", b[0])
		},
	}
	h.Heads[8] = Head{
		IsExit:      true,
		Len:         8,
		Type:        FIX,
		funcDataStr: ParseStr,
	}
	h.Heads[9] = Head{
		IsExit: true,
		Len:    1,
		Type:   FIX,
		funcDataStr: func(b []byte) string {
			return fmt.Sprintf("%d", b[0])
		},
	}
	h.Heads[10] = Head{
		IsExit:      true,
		Len:         5,
		Type:        FIX,
		funcDataStr: ParseStr,
	}
	return h
}

//Do 处理头部数据
func (header *Header) Do(h []byte, p *Position) {
	//获取头部数据
	hd := h[0:header.HeadLen]
	p.Add(header.HeadLen)
	header.parse(hd)
}

//Parse 解析头
func (header *Header) parse(h []byte) {
	if len(h) != 46 {
		panic("解析报文头数据不正确")
	}

	startIndex := 0
	for i := 1; i < len(header.Heads); i++ {
		//Head1 头长度（Header Length） 1
		headElement := header.Heads[i]
		header.Heads[i].Data = h[startIndex : startIndex+headElement.Len]

		header.Heads[i].DataStr = strings.TrimSpace(headElement.funcDataStr(header.Heads[i].Data))
		startIndex += headElement.Len
	}
	//报文长度

	en, err := strconv.Atoi(header.Heads[3].DataStr)
	if err != nil {
		fmt.Println(err)
	}
	header.Len = en
}

//ToString 格式化输出
func (header *Header) ToString() string {
	var buf bytes.Buffer
	heads := header.Heads
	buf.WriteString("Header:[\n")
	buf.WriteString(fmt.Sprintf(" HeadLen:%d	\n", header.HeadLen))
	buf.WriteString(fmt.Sprintf(" Lend:%d	\n", header.Len))

	for index, h := range heads {
		if !h.IsExit {
			continue
		}
		buf.WriteString(fmt.Sprintf("	Field%d:%s 	%+v\n", index, h.DataStr, h))
	}
	buf.WriteString("]")

	return buf.String()
}
